package io.github.mymonstercat.base;

import com.benjaminwan.ocrlibrary.OcrResult;
import com.benjaminwan.ocrlibrary.TextBlock;
import io.github.mymonstercat.Model;
import io.github.mymonstercat.ocr.InferenceEngine;
import io.github.mymonstercat.ocr.config.HardwareConfig;
import io.github.mymonstercat.ocr.config.ParamConfig;
import org.apache.commons.lang3.StringUtils;
import org.simmetrics.StringMetric;
import org.simmetrics.metrics.StringMetrics;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

public class BaseController {
    @Resource
    protected Environment environment;

    public static final String ZERO = "0";

    public static final int ONE = 1;
    @Value("${file.upload.window}")
    protected String window;

    @Value("${file.upload.linux}")
    protected String linux;

    @Value("${file.point}")
    protected String[] point;

    @Value("${file.threshold}")
    protected String threshold;

    public static ParamConfig PARAM_CONFIG = ParamConfig.getDefaultConfig();
    public static InferenceEngine ENGINE = InferenceEngine.getInstance(Model.ONNX_PPOCR_V4, new HardwareConfig(Runtime.getRuntime().availableProcessors()/-1, -1));
    static {
	PARAM_CONFIG.setDoAngle(true);
	PARAM_CONFIG.setMostAngle(true);
	PARAM_CONFIG.setPadding(20);
    }

    public static void uploadFile(MultipartFile file, String path, String name) throws IOException {
	File destinationFile = new File(path);

	if(!destinationFile.exists()) {
	    boolean b = destinationFile.mkdirs();
	}
	OutputStream fos = new FileOutputStream(path + name);
	FileInputStream fis = (FileInputStream) file.getInputStream();
	byte[] buffer = new byte[1024];
	int bytesRead;
	while ((bytesRead = fis.read(buffer)) != -1) {
	    fos.write(buffer, 0, bytesRead);
	}
	fis.close();
	fos.close();
    }

    protected String getRate(MultipartFile file, String fileName, String path, String osName) throws IOException {
	// 阈值
	if(StringUtils.isBlank(threshold)) {
	    threshold = "0.6";
	}
	double target = Double.parseDouble(threshold) * 100d;
	BigDecimal bigDecimal = new BigDecimal(Double.toString(target));

	// 开始识别
	OcrResult ocrResult = ENGINE.runOcr(path + fileName, PARAM_CONFIG);
	ArrayList<TextBlock> arr = ocrResult.getTextBlocks();
	List<Double> rates = new ArrayList<>();
	for (String ss : point) {
	    String[] points = ss.split("\\|");
	    for (String s : points) {
		for (TextBlock t : arr) {
		    String str = t.getText().replaceAll("\\s+", "");
		    StringMetric levenshtein = StringMetrics.levenshtein();
		    double similarity = levenshtein.compare(s, str) * 100d;
		    if(similarity >= target) {
			rates.add(similarity);
		    }
		}
	    }
	    if(rates.size() > 0) {
		BigDecimal average = rates.stream().map(BigDecimal::valueOf).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(rates.size()), 2, RoundingMode.HALF_UP);
		if(average.compareTo(bigDecimal) >= 0) {
		    String satisfy;
		    // 普联不识别并且相似度大于等于60的文件保存位置
		    if(osName.startsWith("Windows")) {
			satisfy = environment.getProperty("file.save.satisfy.window");
		    } else {
			satisfy = environment.getProperty("file.save.satisfy.linux");
		    }
		    uploadFile(file, satisfy, fileName);
		    return average.toString();
		}
	    }
	}
	// 普联不识别并且相似度小于60的文件保存位置
	String dissatisfy;
	// 普联不识别并且相似度大于等于60的文件保存位置
	if(osName.startsWith("Windows")) {
	    dissatisfy = environment.getProperty("file.save.dissatisfy.window");
	} else {
	    dissatisfy = environment.getProperty("file.save.dissatisfy.linux");
	}
	uploadFile(file, dissatisfy, fileName);
	return "0";
    }
}
